using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace WindowsGame2
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D back;
        Texture2D gameOver;
        Texture2D playButton;
        Vector2 buttonPostition;
        Rectangle screen;
        Boy boy;
        Rock[] rocks;
        GameState State;
        MyMouse myMouse;

        KeyboardState keyboardState;

        SoundEffect boom;
        SoundEffectInstance soundinstance;

        enum GameState
        {
            Palying,
            StartScreen,
            GameOver
        }

        Random random;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            graphics.PreferredBackBufferWidth = 900;
            graphics.PreferredBackBufferHeight = 540;
            screen = new Rectangle(0, 0, 900, 540);
            random = new Random();
            Content.RootDirectory = "Content";
            rocks = new Rock[5];
            State = GameState.StartScreen;
            
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            Texture2D rock = Content.Load<Texture2D>("rock");
            Texture2D boy = Content.Load<Texture2D>("boy");
            Texture2D life = Content.Load<Texture2D>("heart");
            Texture2D mouse = Content.Load<Texture2D>("mouse");
            back = Content.Load<Texture2D>("back");
            playButton = Content.Load<Texture2D>("play");
            gameOver = Content.Load<Texture2D>("gameover");

            boom = Content.Load<SoundEffect>("boom");
            soundinstance = boom.CreateInstance();

            myMouse = new MyMouse(mouse);
            buttonPostition = new Vector2((screen.Width - playButton.Width) / 2, (screen.Height - playButton.Height) / 2);
            //Song sf = Content.Load<Song>("backmusic");
            //MediaPlayer.Volume = 0.2f;
            //MediaPlayer.Play(sf);


            this.boy = new Boy(boy, screen, life, soundinstance);
            //creating many rocks
            rocks[0] = new Rock(rock, screen);
            rocks[1] = new Rock(rock, screen);
            rocks[2] = new Rock(rock, screen);
            rocks[3] = new Rock(rock, screen);
            rocks[4] = new Rock(rock, screen);
            foreach (Rock r in rocks)
            {

                r.ResetPosition(random);
            }

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            keyboardState = Keyboard.GetState();

            switch (State)
            {
                case GameState.StartScreen:
                    myMouse.Update();
                    checkClick();
                    break;
                case GameState.Palying: 
                    if (boy.BoyState != Boy.State.Dead)
                    {
                        boy.UpdateFrame((float)gameTime.ElapsedGameTime.TotalSeconds);
                        boy.Update();
                        boy.CheckCollition(rocks);
                        foreach (Rock rock in rocks)
                        {
                            rock.Update();
                            if (rock.rockState == Rock.State.OutOfScreen)
                                rock.ResetPosition(random);
                        }
                    }
                    else
                    {
                        
                        if (keyboardState.IsKeyDown(Keys.Enter))
                        {
                            boy.ReStart();
                        }
                    }
                    break;
            }

           

            base.Update(gameTime);
        }

        private void checkClick()
        {
            MouseState m = Mouse.GetState();
            if (m.LeftButton == ButtonState.Pressed)
            {
                State = GameState.Palying;
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);


            spriteBatch.Begin();
            spriteBatch.Draw(back, Vector2.Zero, Color.White);
            switch (State)
            {
                case GameState.StartScreen:
                    spriteBatch.Draw(playButton, buttonPostition, Color.White);
                    myMouse.Draw(spriteBatch);
                    break;
                case GameState.Palying: if (boy.BoyState != Boy.State.Dead)
                    {
                        boy.Draw(spriteBatch);
                        foreach (Rock rock in rocks)
                            rock.Draw(spriteBatch);
                    }
                    else
                    {
                        spriteBatch.Draw(gameOver, new Vector2((screen.Width - gameOver.Width) / 2, (screen.Height - gameOver.Height) / 2), Color.White);
                    }
                    break;
            }
            
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}
